/* 
 * Copyright (c)	Insighten Intelligent Equipment co.,LTD
 * 
 *  Use of this software is controlled by the terms and conditions found
 *  in the license agreement under which this software has been supplied.
 * 
 */
/** 
 * @file request.c
 * @brief process request
 * @author taco [tacoee@gmail.com]
 * @version 0.1
 * @date 2010-09-10
 */

#include "tcp_server.h"
#include "request.h"
#include "types.h"

static Ret get_command(Request *req)
{
	return_val_if_fail(req != NULL, RET_FAIL);

	char *check = req->buf->mem + req->buf->rpos;
	char *buf_end = req->buf->mem + req->buf->wpos;
	Command *cmd = NULL;
	int value_flag = 0;
	int i = 0;

	cmd = command_new();

	return_val_if_fail(cmd != NULL, RET_FAIL);

	
	while(check < req->cmd_end_pos) {
		if(*check == '?') {
			value_flag = 1;
		}
		if (value_flag) {
			cmd->cmd_val[i] = *check;
		} else {
			cmd->cmd_name[i] = *check;
		}
		check++;
		i++;
	}
	buf_update_rpos(req->buf, (check-req->cmd_end_pos));

	command_enqueue(&req->cmd, cmd);

	return RET_OK;
}
	

static Ret get_method(Request *req)
{
	return_val_if_fail(req != NULL, RET_FAIL);

	if (!memcmp(req->buf->mem, "GET ", 4)) {
		req->method = M_GET;
		buf_update_rpos(req->buf, 6); /*2 for \r\n*/
	} else if (!memcmp(req->buf->mem, "POST ", 5)) {
		req->method = M_POST;
		buf_update_rpos(req->buf, 7); /*2 for \r\n*/
	} else {
		return RET_QUIT;
	}

	return RET_OK;
}

/** brief: read header and process
 * @return 0 means compelete; -1 means error; 1 means more something to do
 */
int read_header(Request *req)
{
	return_val_if_fail(req != NULL, -2);

	int  bytes_left;

	char *check;
	char *buffer;
	int rd;
	int ret;

	buffer = req->buf->mem;
	int bytes = req->buf->wpos;

	check  = req->buf->mem + req->parse_pos;

	while(check < (buffer + bytes)) {
		switch (req->status) {
			case READ_HEADER:
				if (*check == '\r') {
					req->status = ONE_CR;
				} else if (*check == '\n') {
					req->status = ONE_LF;
			//		req->cmd_end_pos = check;
				}
				break;

			case ONE_CR:
				if (*check == '\n') {
					req->status = ONE_LF;
					req->cmd_end_pos = check;
				}
				else if (*check != '\r')
					req->status = READ_HEADER;
				break;

			case ONE_LF:
				/* if here, we've found the end (for sure) of a header */
				if (*check == '\r') /* could be end o headers */
					req->status = TWO_CR;
				else if (*check == '\n')
					req->status = BODY_READ;
				else
					req->status = READ_HEADER;
				break;

			case TWO_CR:
				if (*check == '\n')
					req->status = BODY_READ;
				else if (*check != '\r')
					req->status = READ_HEADER;
				break;

			default:
				break;
		}
		check++;
		req->parse_pos++;

		if (req->status == ONE_LF) {	/*parse one command*/
			*req->cmd_end_pos = '\0';
			if (req->method == M_NO) {	/*Get command type M_POS or M_GET*/
				ret = get_method(req);
				if (ret != RET_OK) {
					return -1;	/*some thing wrong and quit*/
				}
			}
			ret = get_command(req);

			if (ret != RET_OK) {
				return -1;
			}
		}

	} /*while have data in buffer no parse*/

	if (req->status < BODY_READ) {  /*read more data*/
 		bytes_left = req->buf->totalsize - req->buf->wpos;
		rd = tcp_server_read(req, bytes_left);

		if (rd == -2) {
			return 1;
		} else if (rd == -1) {
			return -1;
		} else {
			buf_update_wpos(req->buf, rd);
		}
	}

    return 1;
}

